package com.xique.door.project.xyl.service.impl;

import com.xique.common.core.text.Convert;
import com.xique.common.core.utils.DateUtils;
import com.xique.common.core.utils.MathUtil;
import com.xique.common.core.utils.SecurityUtils;
import com.xique.common.core.utils.StringUtils;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.dao.RentHouseUserCountStatisticDAO;
import com.xique.door.bean.domain.*;
import com.xique.door.mapper.BuildHouseUserMapper;
import com.xique.door.mapper.ParkInfoMapper;
import com.xique.door.mapper.UserMapper;
import com.xique.door.project.xyl.bean.domain.UserStatistics;
import com.xique.door.project.xyl.bean.domain.XylAlarmRecord;
import com.xique.door.project.xyl.bean.vo.SummaryStatisticsVo;
import com.xique.door.project.xyl.mapper.XylAlarmRecordMapper;
import com.xique.door.project.xyl.service.IxylService;
import com.xique.door.service.IBuildBuildingService;
import com.xique.door.service.IBuildHouseService;
import com.xique.door.service.IBuildHouseUserService;
import com.xique.door.project.xyl.service.IXylAlarmRecordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: caogq
 * @Date: 2021/12/27 17:03
 * @Description:
 */
@Service
public class XylAlarmRecordServiceImpl implements IXylAlarmRecordService {
    @Autowired
    private XylAlarmRecordMapper xylAlarmRecordMapper;
    @Autowired
    private ParkInfoMapper parkInfoMapper;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IBuildHouseUserService buildHouseUserService;

    @Autowired
    private BuildHouseUserMapper buildHouseUserMapper;

    @Autowired
    private IxylService xylService;


    @Autowired
    private IBuildBuildingService buildingService;

    @Autowired
    private IBuildHouseService houseService;

    /**
     * 查询西洋楼报警记录
     *
     * @param id 西洋楼报警记录ID
     * @return 西洋楼报警记录
     */
    @Override
    public XylAlarmRecord selectXylAlarmRecordById(Long id) {
        return xylAlarmRecordMapper.selectXylAlarmRecordById(id);
    }

    /**
     * 查询西洋楼报警记录列表
     *
     * @param xylAlarmRecord 西洋楼报警记录
     * @return 西洋楼报警记录
     */
    @Override
    public List<XylAlarmRecord> selectXylAlarmRecordList(XylAlarmRecord xylAlarmRecord) {
        return xylAlarmRecordMapper.selectXylAlarmRecordList(xylAlarmRecord);
    }

    /**
     * 新增西洋楼报警记录
     *
     * @param xylAlarmRecord 西洋楼报警记录
     * @return 结果
     */
    @Override
    public int insertXylAlarmRecord(XylAlarmRecord xylAlarmRecord) {
        xylAlarmRecord.setCreateTime(DateUtils.getNowDate());
        return xylAlarmRecordMapper.insertXylAlarmRecord(xylAlarmRecord);
    }

    /**
     * 修改西洋楼报警记录
     *
     * @param xylAlarmRecord 西洋楼报警记录
     * @return 结果
     */
    @Override
    public int updateXylAlarmRecord(XylAlarmRecord xylAlarmRecord) {
        xylAlarmRecord.setUpdateTime(DateUtils.getNowDate());
        return xylAlarmRecordMapper.updateXylAlarmRecord(xylAlarmRecord);
    }

    /**
     * 删除西洋楼报警记录对象
     *
     * @param ids 需要删除的数据ID
     * @return 结果
     */
    @Override
    public int deleteXylAlarmRecordByIds(String ids) {
        return xylAlarmRecordMapper.deleteXylAlarmRecordByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除西洋楼报警记录信息
     *
     * @param id 西洋楼报警记录ID
     * @return 结果
     */
    @Override
    public int deleteXylAlarmRecordById(Long id) {
        return xylAlarmRecordMapper.deleteXylAlarmRecordById(id);
    }

    @Override
    @Transactional
    public AjaxResult alarmStatistics() {
        List<ParkInfo> parkInfos = parkInfoMapper.selectParkInfoList(new ParkInfo("西洋溇商区"));
        if (parkInfos.isEmpty()) {
            return AjaxResult.error("项目不存在");
        }
        //step1：查询符合条件的报警记录
        Long parkId = parkInfos.get(0).getId();
        List<User> totalUsers = userMapper.selectUserList(new User(parkId));
        //查询7日内西洋楼所有用户进出次数
        List<UserStatistics> last7DaysInoutTime = xylAlarmRecordMapper.countLast7DaysInoutTime(parkId, DateUtils.getPastDay(7));
        List<Long> userInoutUserIds = last7DaysInoutTime.stream().map(UserStatistics::getUserId).collect(Collectors.toList());
        //查询7日内西洋楼所有用户访客数量
        List<UserStatistics> last7DaysVisitorNums = xylAlarmRecordMapper.countLast7DaysVisitorNums(parkId, DateUtils.getPastDay(7));
        //查询7日内西洋楼所有用户访客进出次数
        List<UserStatistics> last7DaysVisitorInoutTime = xylAlarmRecordMapper.countLast7DaysVisitorInoutTime(parkId, DateUtils.getPastDay(7));
        //报警类型1：7日内用户未进出
        List<Long> alarmType1UserIds = totalUsers.stream().filter(e -> !userInoutUserIds.contains(e.getId())).map(User::getId).collect(Collectors.toList());
        //报警类型2：7日内用户访客数量过多
        List<Long> alarmType2UserIds = last7DaysVisitorNums.stream().filter(e -> e.getCount() >= 5).map(UserStatistics::getUserId).collect(Collectors.toList());
        //报警类型3：7日内用户的访客进出次数过多
        List<Long> alarmType3UserIds = last7DaysVisitorInoutTime.stream().filter(e -> e.getCount() >= 5).map(UserStatistics::getUserId).collect(Collectors.toList());
        List<Long> userIdList = new ArrayList<>();
        userIdList.addAll(alarmType1UserIds);
        userIdList.addAll(alarmType2UserIds);
        userIdList.addAll(alarmType3UserIds);
        List<Long> alarmUserIds = userIdList.stream().distinct().collect(Collectors.toList());
        List<User> users = userMapper.selectUserByIds(alarmUserIds, null);
        for (User user : users) {
            Boolean alarmType1Flag = false;
            Boolean alarmType2Flag = false;
            Boolean alarmType3Flag = false;
            String type = "";
            if (alarmType1UserIds.contains(user.getId())){
                alarmType1Flag = true;
            }
            if (alarmType2UserIds.contains(user.getId())){
                alarmType2Flag = true;
            }
            if (alarmType3UserIds.contains(user.getId())){
                alarmType3Flag = true;
            }

            if (alarmType1Flag && !alarmType2Flag && !alarmType3Flag){
                type = "1";
            }else if (!alarmType1Flag && alarmType2Flag && !alarmType3Flag){
                type = "2";
            }else if (!alarmType1Flag && !alarmType2Flag && alarmType3Flag){
                type = "3";
            }else if (alarmType1Flag && alarmType2Flag && !alarmType3Flag){
                type = "1,2";
            }else if (!alarmType1Flag && alarmType2Flag && alarmType3Flag){
                type = "2,3";
            }else if (alarmType1Flag && alarmType2Flag && alarmType3Flag){
                type = "1,2,3";
            }
            user.setType(type);
        }


//        List<VerifyRecords> verifyRecords = xylAlarmRecordMapper.selectLastDaysNoInoutRecords(parkId, DateUtils.getPastDay(7));
//        List<Long> userIds = verifyRecords.stream().filter(e -> e.getUserId() != null).map(VerifyRecords::getUserId).collect(Collectors.toList());
//        List<User> users1 = xylAlarmRecordMapper.selectUserByIds(userIds);
//        List<User> users2 = xylAlarmRecordMapper.selectLastDaysVisitorAlarmRecords(parkId, DateUtils.getPastDay(7));
//        List<User> users3 = xylAlarmRecordMapper.selectLastDaysVisitorInoutAlarmRecords(parkId, DateUtils.getPastDay(7));
//        List<User> userList = new ArrayList<>();
//        userList.addAll(users1);
//        userList.addAll(users2);
//        userList.addAll(users3);
//        List<Long> longUserIds = userList.stream().map(User::getId).collect(Collectors.toList());


        //step2：批查询vo需要的一些数据
        List<String> strUserIds = MathUtil.convertLongToStringList(alarmUserIds);
        Map<String, Object> houseCodeMap = buildHouseUserService.batchSelectFreeviewHouseCodeByUserIds(strUserIds);
        List<BuildHouseUser> buildHouseUsers = buildHouseUserMapper.batchSelectHouseUserByUserIds(strUserIds);
        Map<Long, Object> censusRegisterMap = xylService.selectCensusRegisterByUserIds(alarmUserIds);
        List<Long> buildingIds = buildHouseUsers.stream().map(BuildHouseUser::getBuildingId).collect(Collectors.toList());
        Map<Long, String> buildingMap = buildingService.selectBuildingName(buildingIds);
        List<Long> houseIds = buildHouseUsers.stream().map(BuildHouseUser::getHouseId).collect(Collectors.toList());
        List<RentHouseUserCountStatisticDAO> rentHouseUserCountStatisticDAOS = houseService.selectRentHouseUserCountStatisticByHouse(houseIds);
        Map<Long, Integer> houseUserNumMap = rentHouseUserCountStatisticDAOS.stream().collect(Collectors.toMap(RentHouseUserCountStatisticDAO::getHouseId, RentHouseUserCountStatisticDAO::getUserCount));
        //step3：封装vo
        List<XylAlarmRecord> xylAlarmRecords = new ArrayList<>();
        for (User user : users) {
            XylAlarmRecord xylAlarmRecord = new XylAlarmRecord();
            xylAlarmRecord.setUserName(user.getUserName());
            if (censusRegisterMap != null &&  censusRegisterMap.get(user.getId())!=null){
                xylAlarmRecord.setCensusRegister( String.valueOf(censusRegisterMap.get(user.getId())));
            }
            if (houseCodeMap != null && houseCodeMap.get(String.valueOf(user.getId()))!=null){
                xylAlarmRecord.setHouseCode( String.valueOf(houseCodeMap.get(String.valueOf(user.getId()))));
            }

            BuildHouseUser houseuser = buildHouseUsers.stream().filter(e -> e.getUserId().equals(user.getId())).findFirst().orElse(null);
            if (houseuser != null){
                xylAlarmRecord.setCheckInDate(houseuser.getCheckInDate());
                xylAlarmRecord.setBuildingId(houseuser.getBuildingId());
                if (buildingMap != null && StringUtils.isNotEmpty(buildingMap.get(houseuser.getBuildingId()))){
                    xylAlarmRecord.setBuildingName(buildingMap.get(houseuser.getBuildingId()));
                }
                if (houseUserNumMap!=null && StringUtils.isNotNull(houseUserNumMap.get(houseuser.getHouseId()))) {
                    xylAlarmRecord.setInPersonNum(houseUserNumMap.get(houseuser.getHouseId()));
                }
            }

            UserStatistics userInoutNum = last7DaysInoutTime.stream().filter(e -> user.getId().equals(e.getUserId())).findFirst().orElse(null);
            UserStatistics visitorNum = last7DaysVisitorNums.stream().filter(e -> e.getUserId().equals(user.getId())).findFirst().orElse(null);
            UserStatistics visitorInoutNum = last7DaysVisitorInoutTime.stream().filter(e -> e.getUserId().equals(user.getId())).findFirst().orElse(null);
            int initUserInoutNum = 0;
            int initVisitorNum = 0;
            int initvisitorInoutNum = 0;
            if (userInoutNum != null){
                initUserInoutNum = userInoutNum.getCount();
            }
            if (userInoutNum != null){
                initVisitorNum =  visitorNum.getCount();
            }
            if (userInoutNum != null){
                initvisitorInoutNum = visitorInoutNum.getCount();
            }
            xylAlarmRecord.setInoutNum(initUserInoutNum);
            xylAlarmRecord.setVisitiorNum(initVisitorNum);
            xylAlarmRecord.setVisitiorInoutNum(initvisitorInoutNum);
            //告警状态：默认未处理
            xylAlarmRecord.setStatus("1");
            xylAlarmRecord.setReason(user.getType());
            xylAlarmRecord.setCreateTime(new Date());
            xylAlarmRecord.setUpdateTime(new Date());
            xylAlarmRecords.add(xylAlarmRecord);
        }
        if (!xylAlarmRecords.isEmpty()){
            xylAlarmRecordMapper.batchInsertAlarmRecords(xylAlarmRecords);
        }

        return AjaxResult.success();
    }

    @Override
    public SummaryStatisticsVo summaryStatistics() {
        List<XylAlarmRecord> xylAlarmRecords = xylAlarmRecordMapper.selectXylAlarmRecordList(new XylAlarmRecord());
        int processNum = (int)xylAlarmRecords.stream().filter(e -> "2".equals(e.getStatus())).count();
        long count = xylAlarmRecords.stream().filter(e -> e.getCreateTime() != null && e.getCreateTime().after(DateUtils.getPastDay(7))).count();
        SummaryStatisticsVo summaryStatisticsVo = new SummaryStatisticsVo();
        summaryStatisticsVo.setTotalAlarmNum(xylAlarmRecords.size());
        summaryStatisticsVo.setWeekAlarmNum((int) count);
        summaryStatisticsVo.setUnProcessedNum(xylAlarmRecords.size() - processNum);
        summaryStatisticsVo.setProcessedNum(processNum);
        if (xylAlarmRecords.size() == 0){
            summaryStatisticsVo.setResponseRate(0.0);
        }else {
            summaryStatisticsVo.setResponseRate(MathUtil.div(processNum * 100,xylAlarmRecords.size(),0) );
        }
        return summaryStatisticsVo;
    }

}
